package com.sm.imlibrary.nio;

import androidx.annotation.IntDef;

import com.alibaba.fastjson.JSONObject;
import com.scorpio.baselibrary.PoorApplication;
import com.scorpio.baselibrary.utils.DeviceIdUtil;
import com.scorpio.baselibrary.utils.JSONUtil;
import com.scorpio.baselibrary.utils.Platform;
import com.sm.imlibrary.Constants;
import com.sm.imlibrary.roondao.RoomDaoApi;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.URISyntaxException;
import java.util.logging.Logger;

import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;
import io.socket.engineio.client.EngineIOException;
import io.socket.engineio.client.transports.WebSocket;

/**
 * created by zhud on 2019/7/11
 */
public class SocketIoManage {
    private final Logger logger = Logger.getLogger(SocketIoManage.class.getSimpleName());

    private Socket mSocket;
    private static SocketIoManage mIoService;
    private LoginCallbackListener loginCallbackListener;
    private Platform mPlatform;
    private String identifying;

    private SocketIoManage() {
        mPlatform = Platform.get();
    }

    public String getIdentifying() {
        return identifying;
    }

    public static SocketIoManage getInstance() {
        if (mIoService == null) mIoService = new SocketIoManage();
        return mIoService;
    }

    public void login(String token, LoginCallbackListener loginCallbackListener) {
        stop();
        this.loginCallbackListener = loginCallbackListener;
        try {
            IO.Options options = new IO.Options();
            options.transports = new String[]{WebSocket.NAME};
            options.forceNew = true;
            options.query = String.format("uniqueId=%s&accountToken=%s", DeviceIdUtil.getDeviceId(PoorApplication.getInstance()), token);
            mSocket = IO.socket(Constants.CHAT_SERVER_URL, options);
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
        init();
    }

    public void stop() {
        if (mSocket != null) {
            mSocket.disconnect();
            mSocket.off();
        }
    }

    private void init() {
        mSocket.on(Socket.EVENT_CONNECT, onConnect)
                .on(Socket.EVENT_DISCONNECT, onDisconnect)
                .on(Socket.EVENT_ERROR, onError)
                .on(Socket.EVENT_CONNECT_ERROR, onError)
                .on(Constants.EVENT_LOGIN, onLogin)
                .on(Constants.EVENT_NEW_MESSAGE, onNewMessage);
        mSocket.connect();
    }

    //已连接
    private Emitter.Listener onConnect = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            System.out.println(Socket.EVENT_CONNECT);
        }
    };

    //连接断开
    private Emitter.Listener onDisconnect = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            logger.info(Socket.EVENT_DISCONNECT);
            sendLoginCallback(Constants.FAIL_CODE, null);
        }
    };

    //连接错误
    private Emitter.Listener onError = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            logger.info(Socket.EVENT_ERROR);
            for (Object exception : args) {
                System.out.println(args);
                if (exception instanceof EngineIOException) {

                }
            }
            sendLoginCallback(Constants.FAIL_CODE, null);
        }
    };

    private Emitter.Listener onLogin = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            for (Object arg : args) {
                JSONObject json = JSONUtil.toJSONObject((org.json.JSONObject) arg);
                sendLoginCallback(json.getIntValue("code"), json.getString("data"));
            }
            mSocket.off(Constants.EVENT_LOGIN, this);
        }
    };

    //新的消息
    private Emitter.Listener onNewMessage = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            for (Object arg : args) {
                JSONObject json = JSONUtil.toJSONObject((org.json.JSONObject) arg);
                sendLoginCallback(json.getIntValue("code"), json.getString("data"));
            }
        }
    };

    public static final int CONNECT_NO = 0;//未连接
    public static final int CONNECT_UN = 1;//连接中
    public static final int CONNECT_OK = 2;//已连接
    public static final int CONNECT_ERROR = -1;//连接错误
    public static final int DISCONNECT = -2;//断开连接

    @IntDef({CONNECT_NO, CONNECT_UN, CONNECT_OK, CONNECT_ERROR, DISCONNECT})
    @Retention(RetentionPolicy.SOURCE)
    public @interface SocketConnectResult {
    }

    private void sendLoginCallback(final int code, final String identifying) {
        this.identifying = identifying;
        mPlatform.execute(new Runnable() {
            @Override
            public void run() {
                if (loginCallbackListener != null) {
                    if (code == Constants.SUCCEED_CODE) {
                        RoomDaoApi.getInstance().initDatabase(PoorApplication.getInstance(), identifying);
                        loginCallbackListener.onSucceed();
                    } else {
                        loginCallbackListener.onFail();
                        stop();
                    }
                }
                loginCallbackListener = null;
            }
        });
    }
}
